#!/usr/bin/perl
use FindBin;
use lib $FindBin::Bin;
use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/../plib/lib/perl5";

use strict;
use JSON;
use Getopt::Long;
use AutoExecUtils;
use CollectObjCat;
use SwitchBase;

#README
#如果新增其他品牌交换机，OID设置有问题，可能需要修改SwitchSnmp.pm, 修改开头的$BRANDS的定义，增加品牌名。
#参考：SwitchHuaWei.pm
#从SwitchBase.pm继承重载before方法调整snmp oid的设置
#重载after方法，进行数据的调整或者通过其他途径补充数据
#测试：switchcollector --node '{"host":"192.168.0.252","password":"public"}'
sub main {
    $| = 1;    #不对输出进行buffer，便于实时看到输出日志
    AutoExecUtils::setEnv();

    my ( $node, $objType, $defaultCommunity, $timeout );

    my $isVerbose = 0;
    my $inspect   = 0;

    GetOptions(
        'verbose=i'   => \$isVerbose,
        'node=s'      => \$node,
        'community=s' => \$defaultCommunity,
        'objtype=s'   => \$objType,
        'inspect=i'   => \$inspect,
        'timeout=i'   => \$timeout
    );

    if ( not defined($objType) or $objType eq '' ) {
        $objType = 'Swtich';
    }

    my $nodeInfo  = {};
    my $hasOptErr = 0;

    if ( not defined($node) ) {
        $node = $ENV{'AUTOEXEC_NODE'};
    }

    if ( not defined($node) or $node eq '' ) {
        print("ERROR: Option --node not defined.\n");
        $hasOptErr = 1;
    }
    else {
        $nodeInfo = from_json($node);
    }

    if ( not defined($timeout) ) {
        $timeout = 10;
    }

    my $hostname  = $nodeInfo->{host};
    my $protocol  = $nodeInfo->{protocol};
    my $community = $nodeInfo->{password};
    if ( not defined($community) or $community eq '' or ( $protocol ne 'snmp' and $protocol ne 'snmpv3' ) ) {

        #如果执行节点给出的协议不是snmp或者没有给出密码，则使用默认密码选项给出的团体字
        $community = $defaultCommunity;
    }
    if ( not defined($community) or $community eq '' ) {
        $community = 'public';
    }

    my $brand;
    my $switchBase = SwitchBase->new( hostname => $hostname, community => $community, timeout => $timeout, node => $nodeInfo );
    $brand = $switchBase->getBrand();

    if ( not defined($brand) or $brand eq '' ) {
        print("ERROR: Can not discover the firewall device brand.\n");
    }
    else {
        print("INFO: Switch brand: $brand.\n");
    }

    my $switchIns;
    my $switchClass = "Switch$brand";
    if ( -e "$FindBin::Bin/$switchClass.pm" or -e "$FindBin::Bin/lib/$switchClass.pm" ) {
        print("INFO: Has defined class $switchClass, try to load it.\n");
        eval {
            require "$switchClass.pm";
            $switchIns = $switchClass->new( brand => $brand, hostname => $hostname, community => $community, timeout => $timeout, node => $nodeInfo, inspect => $inspect );
        };
        if ($@) {
            print("WARN: Load $switchClass failed, $@");
            print("WARN: Fall back to SwitchBase class.\n");
            $switchIns = $switchBase;
        }
        else {
            print("INFO: Class $switchClass loaded.\n");
        }
    }
    else {
        print("WARN: $switchClass not found.\n");
        print("WARN: Fall back to SwitchBase class.\n");
        $switchIns = $switchBase;
    }

    my $data = $switchIns->collect();

    $data->{BRAND} = $brand;
    if ( not defined( $data->{VENDOR} ) ) {
        $data->{VENDOR} = $data->{BRAND};
    }

    #my $collector = SwitchSnmp->new( hostname => $hostname, community => $community, timeout => $timeout );
    #my $data = $collector->collect();

    my $objCat = CollectObjCat->get('SWITCH');
    $data->{_OBJ_CATEGORY} = $objCat;
    $data->{_OBJ_TYPE}     = $objType;
    $data->{_APP_TYPE}     = $brand;
    $data->{PK}            = CollectObjCat->getPK($objCat);
    $data->{RESOURCE_ID}   = $nodeInfo->{resourceId};
    $data->{MGMT_IP}       = $hostname;

    my $out = {};
    $out->{DATA} = [$data];
    AutoExecUtils::saveOutput($out);
    if ( $isVerbose == 1 ) {
        print("==================\n");
        print( to_json( $data, { pretty => 1 } ) );
        print("==================\n");
    }

    return 0;
}

exit main();
